﻿using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Nxg.Blog.Core;
using Nxg.Blog.Core.Commands;
using Nxg.Blog.Core.Commands.Posts;
using Nxg.Blog.Core.ViewProjections.Home;

namespace Nxg.Blog.Web.Controllers {

    public class HomeController : BaseController {

        private readonly DataContext _context;
        private readonly ISpamShieldService _spamShield;
        private readonly ICommandInvokerFactory _commandInvokerFactory;
        private readonly IViewProjectionFactory _viewFactory;
        public HomeController (DataContext context, IViewProjectionFactory viewFactory, ISpamShieldService spamShield, ICommandInvokerFactory commandInvokerFactory) {
            _context = context;
            _spamShield = spamShield;
            _commandInvokerFactory = commandInvokerFactory;
            _viewFactory = viewFactory;
        }

        [HttpGet ("page/{page:int}")]
        [HttpGet ("/")]
        public IActionResult Index (int page = 1) {
            return Posts (new RecentBlogPostsBindingModel {
                Page = page,
                    Take = 8
            });
        }

        [HttpGet ("/{year:int}/{month:int}/{titleslug}")]
        public IActionResult Index (string titleslug) {
            return ReturnArticle (new BlogPostDetailsBindingModel { Permalink = titleslug }, _spamShield);
        }

        [HttpGet ("/{year:int}/{month:int}")]
        public IActionResult Index (int year, int month) {
            var input = new IntervalBlogPostsBindingModel {
                FromDate = new DateTime (year, month, 1)
            };

            input.ToDate = input.FromDate.AddMonths (1);

            return ReturnArticles (input);
        }

        [HttpPost ("/spam/hash/{tick}")]
        public IActionResult Hash (int tick) {
            return Content (_spamShield.GenerateHash (tick));
        }

        [HttpPost ("/post/comment")]
        public IActionResult Comment (NewCommentCommand command, SpamShield spamShield) {
            var postModel = _viewFactory.Get<BlogPostDetailsBindingModel, BlogPostDetailsViewModel> (new BlogPostDetailsBindingModel { Permalink = command.TitleSlug });
            if (postModel != null) {
                if (!ModelState.IsValid) {
                    return StatusCode (442);
                }
                command.SpamShield = spamShield;
                command.IPAddress = GetIP ();
                command.PostId = postModel.Id;
                var result = _commandInvokerFactory.Handle<NewCommentCommand, CommandResult> (command);
                if (result.Success)
                    return Redirect (string.Format ("{0}#comment_{1}", postModel.Link, 0));
            }
            return NotFound ();
        }

        private string GetIP () {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault ();
            if (string.IsNullOrEmpty (ip)) {
                ip = HttpContext.Connection.RemoteIpAddress.ToString ();
            }
            return ip;
        }

        public IActionResult ReturnArticles (IntervalBlogPostsBindingModel input) {
            var model = _viewFactory.Get<IntervalBlogPostsBindingModel, IntervalBlogPostsViewModel> (input);

            return View ("Archive", model);
        }

        private IActionResult ReturnArticle (BlogPostDetailsBindingModel input, ISpamShieldService spamShield) {
            var model = _viewFactory.Get<BlogPostDetailsBindingModel, BlogPostDetailsViewModel> (input);

            if (model == null)
                return NotFound ();

            ViewBag.Title = model.Title;

            ViewBag.Tick = spamShield.CreateTick (input.Permalink);

            return View ("Details", model);
        }

        [HttpGet ("/tag/{tag}")]
        public IActionResult Tag (string tag) {
            var input = new TaggedBlogPostsBindingModel () { Tag = tag };
            var model = _viewFactory.Get<TaggedBlogPostsBindingModel, TaggedBlogPostsViewModel> (input);
            if (model == null)
                return NotFound ();
            ViewBag.Title = "标签:" + model.Tag;
            return View ("Tagged", model);
        }

        [HttpGet ("/tags/{page:int}")]
        [HttpGet ("/tags")]
        public IActionResult Tags (int page = 1) {
            var tagCloud = _viewFactory.Get<TagCloudBindingModel, TagCloudViewModel> (new TagCloudBindingModel {
                    Threshold = 2
                });
            return View (tagCloud);
        }

        private IActionResult Posts (RecentBlogPostsBindingModel input) {
            var model = _viewFactory.Get<RecentBlogPostsBindingModel, RecentBlogPostsViewModel> (input);
            if (model.Posts.Count () == 0) {
                if (input.Page > 1) {
                    return NotFound ();
                } else {
                    return View(model);
                }
            }
            if (input.Page == 1)
                ViewBag.Title = "首页";
            else
                ViewBag.Title = "文章列表";

            return View (model);
        }
    }
}